iT邦幫忙

2024 iThome 鐵人賽

DAY 7
1

每天的專案會同步到 GitLab 上,可以前往 GitLab 查看。
有興趣的朋友歡迎留言 or 來信討論,我的信箱是 nickchen1998@gmail.com

在昨天的結尾當中,我們有提到 LangChain 中的 Chain,今天我們就來看一下 Chain 的語法該怎麼寫。

取得資料表資訊

延續昨天的文章,如果們要進行更加複雜的查詢,就必須要把資料表的詳細資訊一併傳遞給 LLM,這樣 LLM 才可以協助我們寫出更加完善的查詢語法。
而在 LangChain 當中,當然也幫我們寫好了一個方法讓我們可以直接使用,讓我們看一下下面的範例:

from langchain.chains import create_sql_query_chain
from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_community.utilities import SQLDatabase


env_settings = EnvSettings()
llm = ChatOpenAI(
    api_key=env_settings.OPENAI_API_KEY,
    model_name="gpt-4o"
)

db = SQLDatabase.from_uri("sqlite:///./test.db")
create_query = create_sql_query_chain(db=db, llm=llm)
print(create_query.invoke({"question": "請問 Alice 買了什麼東西?"}))

在這個範例當中,我們使用了 create_sql_query_chain 這個方法,這個方法會幫我們建立一個 Chain,
這個 Chain 會將我們的問題傳遞給 LLM 並且透過資料庫的資訊來產生 SQL 語句,
這樣我們就可以直接透過這個 Chain 來取得我們想要的 SQL 語句,然而我們可以看一下下方的執行結果:

sql query

可以看到在執行結果中,我們成功的取得了我們想要的 SQL 語句,不過這個語句還是有一些問題,我們需要去除一些雜訊,因此我們寫了這個小 function:

import re
def clean_sql_query(query):
    sql_query = query.replace("```sql\n", "").replace("\n```", "").strip().replace("\n", " ")
    pattern = r'SELECT.*'
    match = re.search(pattern, sql_query, re.DOTALL | re.IGNORECASE)

    return match.group() if match else sql_query

串聯 Chain

接著就是要將我們的兩個動作串連起來了,在 LangChain 當中,不同的兩個動作,我們稱為 Operator,有學過 Airflow 的朋友應該會很眼熟,
沒錯,在 LangChain 當中同樣也可以使用類似於 Airflow 的語法來進行撰寫,讓我們看一下下面的範例:

import re
from langchain.chains import create_sql_query_chain
from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_community.utilities import SQLDatabase
from langchain_community.tools import QuerySQLDataBaseTool


def clean_sql_query(query):
    sql_query = query.replace("```sql\n", "").replace("\n```", "").strip().replace("\n", " ")
    pattern = r'SELECT.*'
    match = re.search(pattern, sql_query, re.DOTALL | re.IGNORECASE)

    return match.group() if match else sql_query


env_settings = EnvSettings()
llm = ChatOpenAI(
    api_key=env_settings.OPENAI_API_KEY,
    model_name="gpt-4o"
)

db = SQLDatabase.from_uri("sqlite:///./test.db")
create_query = create_sql_query_chain(db=db, llm=llm)
execute_query = QuerySQLDataBaseTool(db=db)


chain = create_query | clean_sql_query | execute_query
print(chain.invoke({"question": "請問 Alice 買了什麼東西?"}))

可以看到我們透過 | 這個符號將三個 Operator 串連起來,這樣我們就可以直接透過 chain.invoke 來執行我們的 Chain,
其中 execute_query 這個參數是我們昨天有提到的 QuerySQLDataBaseTool,這個 Tool 會將 SQL 語句傳遞給資料庫進行操作,
下面來看一下我們的執行結果:

datas

取得前面 Operator 的參數

在查詢出我們要的資料後,我們要將資料連同原始的問題一起傳遞給 LLM 進行回答,這時候我們就需要取得前面 Operator 的參數,
我們可以使用 itemgetter 這個方法來取得,讓我們看一下下面的範例:

import re
from langchain.chains import create_sql_query_chain
from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_community.utilities import SQLDatabase
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_core.prompts import ChatPromptTemplate
from operator import itemgetter


def clean_sql_query(query):
    sql_query = query.replace("```sql\n", "").replace("\n```", "").strip().replace("\n", " ")
    pattern = r'SELECT.*'
    match = re.search(pattern, sql_query, re.DOTALL | re.IGNORECASE)

    return match.group() if match else sql_query



env_settings = EnvSettings()
llm = ChatOpenAI(
    api_key=env_settings.OPENAI_API_KEY,
    model_name="gpt-4o"
)

db = SQLDatabase.from_uri("sqlite:///./test.db")
create_query = create_sql_query_chain(db=db, llm=llm)
execute_query = QuerySQLDataBaseTool(db=db)
search_template = ChatPromptTemplate.from_template(
    """
    原始問題: {question}
    取得的參考資料: {data}
    """,
)


chain = (
    {
        "data": create_query | clean_sql_query | execute_query,
        "question": itemgetter("question")
    }
    | search_template
    | llm
)
ai_message = chain.invoke({"question": "請問 Alice 買了什麼東西?"})
print(ai_message.content)

可以看到在範例當中,我們在第一個 operator 中使用了 itemgetter 來取得 question 這個參數,並且將查詢資料的 chain 寫在 data 這個參數裡面,
這樣我們就可以直接將查詢出的資料作為參數提供給後面的 operator 進行使用。

下面我們看一下執行結果:

result

可以看到在執行結果中,我們成功的取得了我們想要的回答,表示在 search_template 當中有成功使用到我們定義的 data 以及 question 這兩個參數。

內容預告

針對串接語言模型以及 LangChain 基本語法及概念的部分,我們就暫時介紹到這邊,明天開始我們會進入到 Embedding、RAG 以及如何使用 LangChain 來進行問答系統的開發。


上一篇
Day 06 - LangChain 與 SQL
下一篇
Day 08 - Embedding & Pinecone 介紹
系列文
初探 Langchain 與 LLM:打造簡易問診機器人30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言